package com.tyk.bookstore.back.product.controller;


import cn.dev33.satoken.annotation.SaCheckPermission;
import com.tyk.bookstore.back.common.core.excel.ExcelManager;
import com.tyk.bookstore.back.common.core.model.page.PageVo;
import com.tyk.bookstore.back.common.core.model.result.R;
import com.tyk.bookstore.back.common.core.model.type.SuggestionQuery;
import com.tyk.bookstore.back.product.manager.excel.manager.ExcelConstant;
import com.tyk.bookstore.back.product.manager.excel.model.BookExcelVo;
import com.tyk.bookstore.back.product.model.enume.BookState;
import com.tyk.bookstore.back.product.model.query.BookAddQuery;
import com.tyk.bookstore.back.product.model.query.BookPageQuery;
import com.tyk.bookstore.back.product.model.query.BookUpdateQuery;
import com.tyk.bookstore.back.product.model.vo.BookPageVo;
import com.tyk.bookstore.back.product.model.vo.BookSuggestionVo;
import com.tyk.bookstore.back.product.model.vo.BookVo;
import com.tyk.bookstore.back.product.service.BookService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;
import java.util.Set;

/**
 * @author tyk
 * @description 书籍管理
 */
@RequestMapping({"api/product/book"})
@Tag(name = "商品管理/书籍管理", description = "书籍管理")
@RestController
@RequiredArgsConstructor
public class BookController {
    private final BookService bookService;
    private final ExcelManager<BookExcelVo> excelManager;


    @Operation(summary = "获取书籍详情", description = "获取书籍详情")
    @SaCheckPermission("product:book:get")
    @GetMapping({"{id}"})
    public R<BookVo> getById(
            @Schema(description = "书籍ID") @NotNull @Min(1)
            @PathVariable Long id
    ) {
        return R.ok(bookService.getById(id));
    }


    @Operation(summary = "分页查询书籍", description = "分页查询书籍")
    @SaCheckPermission("product:book:page")
    @GetMapping({"page"})
    public R<BookPageVo> getPage(
            @Validated BookPageQuery query,
            BindingResult br
    ) {
        return br.hasErrors() ? R.ok(PageVo.instance(BookPageVo.class)) : R.ok(bookService.getPage(query));
    }


    @Operation(summary = "书籍搜索建议列表", description = "书籍搜索建议列表")
    @SaCheckPermission("product:book:suggest")
    @GetMapping({"suggest"})
    public R<List<BookSuggestionVo>> getSuggestionList(
            @Validated @ParameterObject SuggestionQuery query
    ) {
        return R.ok(bookService.getSuggestionList(query));
    }


    @Operation(summary = "添加书籍", description = "添加书籍")
    @SaCheckPermission("product:book:add")
    @PostMapping
    public R<Object> add(
            @Validated @RequestBody BookAddQuery query
    ) {
        bookService.add(query);
        return R.ok();
    }


    @Operation(summary = "更新书籍", description = "更新书籍")
    @SaCheckPermission("product:book:update")
    @PutMapping
    public R<Object> updateById(
            @Validated @RequestBody BookUpdateQuery query
    ) {
        bookService.updateById(query);
        return R.ok();
    }


    @Operation(summary = "删除书籍", description = "删除书籍")
    @SaCheckPermission("product:book:delete")
    @DeleteMapping({"{id}"})
    public R<Object> deleteById(
            @Schema(description = "书籍ID") @Min(1) @NotNull
            @PathVariable Long id
    ) {
        bookService.deleteById(id);
        return R.ok();
    }


    @Operation(summary = "批量删除书籍", description = "批量删除书籍")
    @SaCheckPermission("product:book:delete")
    @DeleteMapping
    public R<Object> deleteBatchByIdList(
            @Schema(description = "书籍ID列表") @NotNull @NotEmpty Set<Long> idList
    ) {
        bookService.deleteBatchByIdSet(idList);
        return R.ok();
    }


    @Operation(summary = "上架书籍", description = "上架书籍")
    @SaCheckPermission("product:book:on")
    @PutMapping({"on/{id}"})
    public R<Object> on(
            @Schema(description = "书籍ID")
            @NotNull @Min(1)
            @PathVariable Long id
    ) {
        bookService.changeBookStatus(id, BookState.ON);
        return R.ok();
    }


    @Operation(summary = "下架书籍", description = "下架书籍")
    @SaCheckPermission("product:book:off")
    @PutMapping({"off/{id}"})
    public R<Object> off(
            @Schema(description = "书籍ID")
            @NotNull @Min(1)
            @PathVariable Long id
    ) {
        bookService.changeBookStatus(id, BookState.OFF);
        return R.ok();
    }


    @Operation(summary = "上传封面", description = "上传封面")
    @SaCheckPermission("product:book:cover:upload")
    @PostMapping({"cover"})
    public R<String> uploadCover(MultipartFile file) {
        return R.ok(bookService.uploadCover(file));
    }


    @Operation(summary = "上传展示图", description = "上传展示图")
    @SaCheckPermission("product:book:display:multi:upload")
    @PostMapping({"display/multi"})
    public R<List<String>> addDisplayImageList(List<MultipartFile> fileList) {
        return R.ok(bookService.addDisplayImageList(fileList));
    }


    @Operation(summary = "上传展示图", description = "上传展示图")
    @SaCheckPermission("product:book:display:single:upload")
    @PostMapping({"display/single"})
    public R<List<String>> addDisplayImage(MultipartFile file) {
        return R.ok(List.of(bookService.addDisplayImage(file)));
    }


    @Operation(summary = "删除展示图片", description = "删除展示图片")
    @SaCheckPermission("product:book:display:batch:delete")
    @DeleteMapping({"display/list"})
    public R<Object> deleteDisplayImageList(@RequestBody Set<String> urlList) {
        bookService.deleteDisplayImageList(urlList);
        return R.ok();
    }


    @Operation(summary = "导出Excel", description = "导出Excel")
    @SaCheckPermission("product:book:excel:download")
    @GetMapping("excel")
    public void downloadExcel(BookPageQuery query, HttpServletResponse resp) {
        excelManager.write(
                bookService.getBookExcelVoList(query),
                ExcelConstant.BOOK_FILE_NAME,
                ExcelConstant.BOOK_SHEET,
                resp
        );
    }


    @Operation(summary = "导入Excel", description = "导入Excel")
    @SaCheckPermission("product:book:excel:upload")
    @PostMapping("excel")
    public R<Object> uploadExcel(MultipartFile file) {
        excelManager.save(
                file,
                bookService::saveBookExcelVoList
        );
        return R.ok();
    }

    @Operation(summary = "下载Excel模板", description = "下载Excel模板")
//    @SaCheckPermission("product:book:excel:template")
    @GetMapping("excel/template")
    public void excelTemplate(HttpServletResponse resp) {
        excelManager.template(
                ExcelConstant.BOOK_TEMPLATE,
                List.of("书名", "价格", "封面路径", "标题", "书籍简介", "作者ID", "出版社ID", "出版时间", "ISBN", "低级分类ID", "字数[单位：万字]", "重量[单位：克]", "规格"),
                resp
        );
    }

}
